from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin
from utils.common import BaseModel


class UserManager(BaseUserManager):
    def _create_user(self, username, password, **kwargs):
        if not username:
            raise ValueError("必须要传递账号")
        if not password:
            raise ValueError("必须要传递密码")
        user = self.model(username=username, **kwargs)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, password, **kwargs):
        return self._create_user(username=username, password=password, **kwargs)

    def create_superuser(self, username, password, **kwargs):
        kwargs.setdefault('is_superuser', True)
        kwargs.setdefault('is_staff', True)
        kwargs.setdefault('realname', '管理员')
        if kwargs.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')
        return self._create_user(username=username, password=password, **kwargs)


class Account(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(verbose_name='用户名', max_length=100, unique=True, null=False, blank=False)
    mini_program_openid = models.CharField(verbose_name='微信小程序用户的openid', max_length=100, unique=True, null=True)
    realname = models.CharField(verbose_name='姓名', max_length=50, null=True, blank=True)
    telephone = models.CharField(verbose_name='手机号', max_length=30, null=True, blank=True)
    is_active = models.BooleanField(verbose_name='账号是否可用', default=True)
    is_staff = models.BooleanField(verbose_name='是否能登陆到后台', default=False)
    roles = models.ManyToManyField(verbose_name='角色', to="Role", related_name='user_set', related_query_name='user',
                                   blank=True, through='AccountRoles')
    is_company = models.BooleanField(default=1, verbose_name='是否为企业')
    address = models.CharField(verbose_name='地址', max_length=200, null=True)
    ying_ji = models.BooleanField(verbose_name='是否需要做应急预案', default=False)
    jian_kong = models.BooleanField(verbose_name='是否需要做在线监控', default=False)
    batch_num = models.PositiveIntegerField(verbose_name='批次', default=2)  # 1-第一批， 2-第二批
    is_write = models.BooleanField(verbose_name='是否已填', default=False)

    had_write_self_ass = models.BooleanField(verbose_name='是否已经上网站填写自评资料', default=False)
    origin_pwd = models.CharField(verbose_name='密码', null=True, max_length=50)
    is_analysis = models.BooleanField(verbose_name='是否进行分析', default=True)

    created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = []

    objects = UserManager()

    class Meta:
        db_table = "account"
        verbose_name = "账号表"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username

    def get_all_perms(self, add_role_codename=False):
        """获取该用户所有权限的codename，返回一个权限codename的集合"""
        # add_role_codename参数用于判断是否将该用户的角色codename加入到返回的权限列表中
        if self.is_superuser:
            perms_qs = Permission.objects.all().values_list('codename', flat=True)
            perms_set = [perm for perm in perms_qs] + ['admin']
            return set(perms_set)
        perms_set = set()
        role_qs = self.roles.all().values('id', 'codename')
        roles_id = [i['id'] for i in role_qs]
        perms_qs = RolePermissions.objects.filter(role_id__in=roles_id) \
            .values_list('permission__codename', flat=True).distinct()
        for perm in perms_qs:
            perms_set.add(perm)
        if add_role_codename:
            for role_obj in role_qs:
                perms_set.add(role_obj['codename'])
        if self.is_company:
            perms_set.add('company')
        return perms_set

    def is_role(self, role_codename):
        """ 判断一个用户是否为某个角色 """
        if AccountRoles.objects.filter(account=self, role__codename=role_codename).exists():
            return True
        return False

    def in_roles(self, role_codename_lst):
        """ 判断一个用户是否为一组角色中的其中一个 """
        if AccountRoles.objects.filter(account=self, role__codename__in=role_codename_lst).exists():
            return True
        return False

    def had_permission(self, permission_codename):
        """ 判断一个用户是否拥有某个权限 """
        role_ids = AccountRoles.objects.filter(account=self).values_list('role_id', flat=True)
        if RolePermissions.objects.filter(role_id__in=role_ids, permission__codename=permission_codename).exists():
            return True
        return False


class Role(models.Model):
    system_name = models.CharField(verbose_name='所属系统', max_length=20, default='滴滴快修')
    name = models.CharField(verbose_name='角色名', max_length=50, null=False, blank=False)
    codename = models.CharField(verbose_name='角色编码', max_length=50, null=True, blank=True)
    desc = models.CharField(verbose_name='角色描述', max_length=100, default='', blank=True)
    level = models.IntegerField(verbose_name='角色层次', default=1)
    sort_num = models.IntegerField(verbose_name='排序编号', default=0)
    parent = models.ForeignKey('self', verbose_name='父角色', related_name='child',
                               null=True, blank=True, on_delete=models.CASCADE)
    display = models.BooleanField(verbose_name='是否显示', default=True)
    permissions = models.ManyToManyField(verbose_name='权限', to='Permission', related_name='role_set',
                                         related_query_name='role', blank=True, through='RolePermissions')

    class Meta:
        db_table = "role"
        verbose_name = "角色"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class AccountRoles(models.Model):
    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    role = models.ForeignKey(Role, on_delete=models.CASCADE)

    class Meta:
        db_table = "account_roles"
        unique_together = ('account', 'role')


class Permission(models.Model):
    system_name = models.CharField(verbose_name='所属系统', max_length=20, default='滴滴快修')
    name = models.CharField(verbose_name='权限名', max_length=50, null=False, blank=False)
    codename = models.CharField(verbose_name='权限编码', max_length=100, null=False, blank=False)
    sort_num = models.IntegerField(verbose_name='排序编号', null=True, blank=True)
    level = models.IntegerField(verbose_name='菜单层次', null=False, blank=False)
    parent = models.ForeignKey('self', verbose_name='父菜单', related_name='child',
                               null=True, blank=True, on_delete=models.CASCADE)

    class Meta:
        db_table = "permission"
        verbose_name = '权限'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class RolePermissions(models.Model):
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
    role = models.ForeignKey(Role, on_delete=models.CASCADE)

    class Meta:
        db_table = "role_permissions"
        unique_together = ('role', 'permission')


# class MiniprogramAccount(BaseModel):
#     mini_program_openid = models.CharField(verbose_name='微信小程序用户的openid', max_length=100, db_index=True)
#     account = models.ForeignKey(Account, verbose_name='关联账号', on_delete=models.CASCADE)
#
#     class Meta:
#         db_table = 'mini_program_account'
#         verbose_name = '微信小程序用户'
#         verbose_name_plural = verbose_name
